﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Entity;
using System.Threading.Tasks;
using CaltechSoft.Service.EntityFW.Context;
using CaltechSoft.Service.EntityFW.Entity;

namespace CaltechSoft.Service.Repositories
{
    public class BaseRepository<T> : IRepository<T> where T : Entity
    {
        public CaltechContext Context
        {
            get
            {
                return new CaltechContext();
            }
        }

        public virtual IQueryable<T> DbSet()
        {
            var context = Context;
            return context.Set<T>().AsNoTracking();
        }

        public virtual async Task<T> GetBy(int id)
        {
            var context = Context;
            return await context.Set<T>().FirstOrDefaultAsync(item => item.Id == id);
        }

        public virtual async Task<int> Update(T updatedEntity)
        {
            using (var context = Context)
            {
                T attachedEntity = null;

                if (updatedEntity == null)
                {
                    throw new ArgumentException("Cannot add a null entity.");
                }

                var entry = context.Entry<T>(updatedEntity);

                if (entry.State == EntityState.Detached)
                {
                    attachedEntity = context.Set<T>().FirstOrDefault(i => i.Id == updatedEntity.Id);

                    if (attachedEntity != null)
                    {
                        var attachedEntry = context.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(updatedEntity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified;
                    }
                }

                return await context.SaveChangesAsync();
            }
        }

        public virtual async Task<int> Remove(int id)
        {
            using (var context = Context)
            {
                var dbSet = context.Set<T>();

                var entity = dbSet.FirstOrDefault(i => i.Id == id);

                if (entity != null)
                {
                    dbSet.Remove(entity);
                }

                return await context.SaveChangesAsync();
            }
        }


        public virtual async Task<int> Add(T entity)
        {
            using (var context = Context)
            {
                context.Set<T>().Add(entity);
                return await context.SaveChangesAsync();
            }
        }


        public async Task<IList<T>> GetAll()
        {
            using (var context = Context)
            {
                return await context.Set<T>().ToListAsync();
            }
        }
    }
}